#if !BOOST_PP_IS_ITERATING
#  ifndef BOOST__THREAD__DETAILS__LOCK_MATRIX_HPP
#    define BOOST__THREAD__DETAILS__LOCK_MATRIX_HPP

// Copyright (C) 2004-2009
// Alex Turbov, Igor Veresov
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#    include <boost/thread/details/unilock_config.hpp>

#    include <boost/mpl/at.hpp>
#    include <boost/mpl/integral_c.hpp>
#    include <boost/mpl/size.hpp>
#    include <boost/preprocessor/cat.hpp>
#    include <boost/preprocessor/comma_if.hpp>
#    include <boost/preprocessor/iterate.hpp>
#    include <boost/preprocessor/repeat.hpp>
#    include <algorithm>

namespace boost { namespace details {

template <
    typename Sequence
  , int row
  , int col
  >
struct at_ij
{
    typedef typename mpl::at<
        typename mpl::at<
            Sequence
          , mpl::integral_c<int, row>
          >::type
      , mpl::integral_c<int, col>
      >::type type;
};

template <
    typename LockType
  , typename Sequence
  , int Size = mpl::size<Sequence>::type::value
  >
class lock_matrix;

}}                                                         // namespace details, boost

#    define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_MAX_LOCK_MATRIX_SIZE, "boost/thread/details/lock_matrix.hpp"))
#    include BOOST_PP_ITERATE()

#  endif                                                   // BOOST__THREAD__DETAILS__LOCK_MATRIX_HPP
#else                                                      // BOOST_PP_IS_ITERATING

#  define N BOOST_PP_ITERATION()

#  define LOCK_MATRIX_COL(z, n, text) \
    BOOST_PP_COMMA_IF(n) at_ij<Sequence, text, n>::type::value

#  define LOCK_MATRIX_ROW(z, n, text) \
    BOOST_PP_COMMA_IF(n) {BOOST_PP_REPEAT(N, LOCK_MATRIX_COL, n)}

#  define MUL_ROW(z, n, text) \
    BOOST_PP_IF(n, &&, ) (!(m_lock_matrix[t][n] || bool(m_state[n])) || m_lock_matrix[t][n])

#  define CHECK_ROW(z, n, text) \
    BOOST_PP_IF(n, ||, ) (text[n] > 0)

namespace boost { namespace details {

/// \todo Check that LockType is enum and Sequence is conforming to MPL Sequence concept
template <
    typename LockType
  , typename Sequence
  >
class lock_matrix<LockType, Sequence, N>
{
    static const bool m_lock_matrix[N][N];
    int m_state[N];

protected:
    typedef LockType lock_type;

public:
    lock_matrix()
    {
        std::fill_n(m_state, N, false);
    }
    void lock_(LockType t)
    {
        ++m_state[t];
    }
    void unlock_(LockType t)
    {
        --m_state[t];
    }
    bool can_lock(LockType t) const
    {
        return BOOST_PP_REPEAT(N, MUL_ROW, _);
    }
    bool is_locked() const
    {
        return BOOST_PP_REPEAT(N, CHECK_ROW, m_state);
    }
    bool is_locked(LockType t) const
    {
        return m_state[t] > 0;
    }
};

template <
    typename LockType
  , typename Sequence
  >
const bool lock_matrix<LockType, Sequence, N>::m_lock_matrix[N][N] =
{
    BOOST_PP_REPEAT(N, LOCK_MATRIX_ROW, _)
};

}}                                                         // namespace details, boost

#  undef CHECK_ROW
#  undef MUL_ROW
#  undef LOCK_MATRIX_ROW
#  undef LOCK_MATRIX_COL
#  undef N
#endif                                                     // BOOST_PP_IS_ITERATING
